package com.cn.ycy.token;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.SimpleTimeZone;
import java.util.UUID;

public class AlibabaDuanXin {

  // https://help.aliyun.com/document_detail/56189.html?spm=a2c4g.11186623.6.669.8f212e7eQdGjrh
  public static void main(String[] args) throws Exception {
    String accessKeyId = "LTAI4G6nN2AovtrLRxwHjncF";
    String accessSecret = "4nSQY9z79BamTVsEVXTgGbfCYb9X8t";

    java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
    SimpleTimeZone gmt = new SimpleTimeZone(0, "GMT");
    df.setTimeZone(gmt);// 这里一定要设置GMT时区

    java.util.Map<String, String> paras = new java.util.HashMap<String, String>();
    // 1. 系统参数
    paras.put("SignatureMethod", "HMAC-SHA1");
    String value = UUID.randomUUID().toString();
    value = "2ae1c504-cfb5-49b7-89e4-b2ad8df95d25";
    System.out.println("value uuid：" + value);
    paras.put("SignatureNonce", value);
    paras.put("AccessKeyId", accessKeyId);
    paras.put("SignatureVersion", "1.0");
    //Timestamp -> 2021-01-19T11:00:04Z
    String format = df.format(new Date());
    format = "2021-01-19T11:00:04Z";
    paras.put("Timestamp", format);
    paras.put("Format", "XML");

    // 2. 业务API参数
    paras.put("Action", "SendSms");
    paras.put("Version", "2017-05-25");

    paras.put("RegionId", "cn-hangzhou");
    paras.put("PhoneNumbers", "15300000001");
    paras.put("SignName", "阿里云短信测试专用zz*z+z");
    paras.put("TemplateParam", "{\"customer\":\"test\"}");
    paras.put("TemplateCode", "SMS_71390007");
    paras.put("OutId", "123");

    // 3. 去除签名关键字Key
    String signature1 = "Signature";
    if (paras.containsKey(signature1))
      paras.remove(signature1);

    // 4. 参数KEY排序
    java.util.TreeMap<String, String> sortParas = new java.util.TreeMap<String, String>();
    sortParas.putAll(paras);

    // 5. 构造待签名的字符串
    java.util.Iterator<String> it = sortParas.keySet().iterator();
    StringBuilder sortQueryStringTmp = new StringBuilder();
    while (it.hasNext()) {
      String key = it.next();
      sortQueryStringTmp.append("&").append(specialUrlEncode(key)).append("=").append(specialUrlEncode(paras.get(key)));
    }
    StringBuilder sortQueryStringTmp2 = new StringBuilder();
    java.util.Iterator<String> it2 = sortParas.keySet().iterator();
    while (it2.hasNext()) {
      String key = it2.next();
      sortQueryStringTmp2.append("&").append(key).append("=").append((paras.get(key)));
    }

    System.out.println(sortQueryStringTmp2);

    String sortedQueryString = sortQueryStringTmp.substring(1);// 去除第一个多余的&符号

    StringBuilder stringToSign = new StringBuilder();
    stringToSign.append("GET").append("&");
    stringToSign.append(specialUrlEncode("/")).append("&");
    stringToSign.append(specialUrlEncode(sortedQueryString));

    String sign = sign(accessSecret + "&", stringToSign.toString());
    // 6. 签名最后也要做特殊URL编码
    String signature = specialUrlEncode(sign);

    System.out.println(paras.get("SignatureNonce"));
    System.out.println("\r\n=========\r\n");
    System.out.println(paras.get("Timestamp"));
    System.out.println("\r\n=========\r\n");
    System.out.println(sortedQueryString);
    System.out.println("\r\n sortedQueryString =========\r\n");
    System.out.println(stringToSign.toString());
    System.out.println("\r\n stringToSign =========\r\n");
    System.out.println(sign);
    System.out.println("\r\n sign =========\r\n");
    System.out.println(signature);
    System.out.println("\r\n signature =========\r\n");
    // 最终打印出合法GET请求的URL
    System.out.println("http://dysmsapi.aliyuncs.com/?Signature=" + signature + sortQueryStringTmp);

    /**
     * https://dysmsapi.aliyuncs.com/?Signature=wziDfjZ09VzPNz8AjBL0wIjX4So%3D&AccessKeyId=&Action=SendSms&Format=JSON&OutId=123&PhoneNumbers=15300000001&RegionId=cn-hangzhou&SignName=%E9%98%BF%E9%87%8C%E4%BA%91%E7%9F%AD%E4%BF%A1%E6%B5%8B%E8%AF%95%E4%B8%93%E7%94%A8&SignatureMethod=HMAC-SHA1&SignatureNonce=4089e4b0-51a3-11eb-af03-6751c9decc5b&SignatureVersion=1.0&TemplateCode=SMS_71390007&TemplateParam=%7B%22customer%22%3A%22test%22%7D&Timestamp=2021-01-08T11%3A18%3A36Z&Version=2017-05-25
     */

  }

  public static String specialUrlEncode(String value) throws Exception {
    return java.net.URLEncoder.encode(value, "UTF-8")
            .replace("+", "%20")
            .replace("*", "%2A")
            .replace("%7E", "~");
  }

  public static String sign(String accessSecret, String stringToSign) throws Exception {
    javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1");
    mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA1"));
    byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
    return new sun.misc.BASE64Encoder().encode(signData);
  }

}
